while ( v76 != 8573.8567 )Enter your operation: 85738567 / 10000
Result: 8573.856700
Correct! Attempting to decrypt the flag...
I calculated 368 operations, tested each result in the gauntlet, and flipped 119 bits in the encrypted flag!
Here is your decrypted flag:
uiuctf{This is a fake flag. You are too fast!}_BOOL8 __fastcall gauntlet(double a1)
{
return (unsigned __int8)isNegative(a1) || (unsigned __int8)isNotNumber(a1) || (unsigned __int8)isInfinity(a1);
}__int64 v52[1104]; we need the value of thisj_memcpy(v52, "%", sizeof(v52)); seems to fill it with %for ( i = 0; i < 368; ++i )
{
v30 = calculate(v52[3 * i], v52[3 * i + 1], v52[3 * i + 2]);
if (gauntlet(v30) )
{
// flip bit
}
}
They had this check in the end (edited)v52 seems to be size 1104 with all %'s. so idk why it can have calculations donev30 = calculate((__int64)v34, v26, i, v27, v28, v29, v52[3 * i], v52[3 * i + 1], v52[3 * i + 2]); for v52?v30 = calculate((__int64)v34, v26, i, v27, v28, v29, v52[3 * i], v52[3 * i + 1], v52[3 * i + 2]); for v52? if ( gauntlet(v30) ) ? (edited)for ( i = 0; i < (int)val_368; ++i )
{
v47 = calculate((unsigned int)&v54, (_DWORD)v43, i, v44, v45, v46, v73[3 * i], v73[3 * i + 1], v73[3 * i + 2]);
if ( (unsigned __int8)gauntlet(v47) )
{
v63 = i / 8;
v64 = i % 8;
LODWORD(v43) = 1 << (7 - i % 8);
v44 = (unsigned int)v43 ^ *((unsigned __int8 *)flag_shit + i / 8);
*((_BYTE *)flag_shit + v63) ^= 1 << (7 - i % 8);
++v59;
}
}i-th bit in flag (edited)uiuctf{This is a fake flag. You are too fast!}0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0while ( v46 != 8573.8567 ) so is this not even usedUIUC lol, prob trolling?pwndbg> x/50bx 0x7fffffffaf70
0x7fffffffaf70: 0x4b 0xc3 0xe1 0x01 0x00 0xb9 0xee 0x10
0x7fffffffaf78: 0xee 0x4b 0xf0 0xa4 0x78 0x21 0x38 0xcb
0x7fffffffaf80: 0xea 0x2a 0x21 0x6b 0xce 0x83 0x46 0xe8
0x7fffffffaf88: 0x41 0xa7 0x8c 0x2c 0x09 0xcf 0xf5 0xa0
0x7fffffffaf90: 0xa1 0x72 0x27 0x08 0x60 0x28 0xa9 0x20
0x7fffffffaf98: 0x66 0xb3 0xab 0x35 0xa4 0xe9 0x00 0x00pwndbg> x/50bx 0x7fffffffaf70
0x7fffffffaf70: 0x4b 0xc3 0xe1 0x01 0x00 0xb9 0xee 0x10
0x7fffffffaf78: 0xee 0x4b 0xf0 0xa4 0x78 0x21 0x38 0xcb
0x7fffffffaf80: 0xea 0x2a 0x21 0x6b 0xce 0x83 0x46 0xe8
0x7fffffffaf88: 0x41 0xa7 0x8c 0x2c 0x09 0xcf 0xf5 0xa0
0x7fffffffaf90: 0xa1 0x72 0x27 0x08 0x60 0x28 0xa9 0x20
0x7fffffffaf98: 0x66 0xb3 0xab 0x35 0xa4 0xe9 0x00 0x00 8573.8567 ^ 1 and 85738567 / 10000pwndbg> x/50bx $rdx
0x7fffffffaf70: 0x4b 0xc3 0xe1 0x01 0x00 0xb9 0xee 0x10
0x7fffffffaf78: 0xee 0x4b 0xf0 0xa4 0x78 0x21 0x38 0xcb
0x7fffffffaf80: 0xea 0x2a 0x21 0x6b 0xce 0x83 0x46 0xe8
0x7fffffffaf88: 0x41 0xa7 0x8c 0x2c 0x09 0xcf 0xf5 0xa0
0x7fffffffaf90: 0xa1 0x72 0x27 0x08 0x60 0x28 0xa9 0x20
0x7fffffffaf98: 0x66 0xb3 0xab 0x35 0xa4 0xe9 0x00 0x00pwndbg> x/50bx $rdx
0x7fffffffaf70: 0x4b 0xc3 0xe1 0x01 0x00 0xb9 0xee 0x10
0x7fffffffaf78: 0xee 0x4b 0xf0 0xa4 0x78 0x21 0x38 0xcb
0x7fffffffaf80: 0xea 0x2a 0x21 0x6b 0xce 0x83 0x46 0xe8
0x7fffffffaf88: 0x41 0xa7 0x8c 0x2c 0x09 0xcf 0xf5 0xa0
0x7fffffffaf90: 0xa1 0x72 0x27 0x08 0x60 0x28 0xa9 0x20
0x7fffffffaf98: 0x66 0xb3 0xab 0x35 0xa4 0xe9 0x00 0x000, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0 *((_BYTE *)flag_shit + v63) ^= 1 << (7 - i % 8); and this happens i guess?0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0 0, 0, 1, 1, 1, 1, 1, 0 here it shifts 5 times at the beginning but printed flag is still u?import IPython
bit_arr = [0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0]
original_flag = [0x4b, 0xc3, 0xe1, 0x01, 0x00, 0xb9, 0xee, 0x10, 0xee, 0x4b, 0xf0, 0xa4, 0x78, 0x21, 0x38, 0xcb, 0xea, 0x2a, 0x21, 0x6b, 0xce, 0x83, 0x46, 0xe8, 0x41, 0xa7, 0x8c, 0x2c, 0x09, 0xcf, 0xf5, 0xa0, 0xa1, 0x72, 0x27, 0x08, 0x60, 0x28, 0xa9, 0x20, 0x66, 0xb3, 0xab, 0x35, 0xa4, 0xe9]
for i in range(0,len(bit_arr)):
idx = bit_arr[i]
if (idx == 1):
v63 = int(i / 8)
original_flag[v63] ^= 1 << (7 - i % 8);
print(original_flag)
string = ''.join(chr(num) for num in original_flag)
print(string)
IPython.embed()UTFCTF{ is definitely rightimport IPython
bit_arr = [0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0]
original_flag = [0x4b, 0xc3, 0xe1, 0x01, 0x00, 0xb9, 0xee, 0x10, 0xee, 0x4b, 0xf0, 0xa4, 0x78, 0x21, 0x38, 0xcb, 0xea, 0x2a, 0x21, 0x6b, 0xce, 0x83, 0x46, 0xe8, 0x41, 0xa7, 0x8c, 0x2c, 0x09, 0xcf, 0xf5, 0xa0, 0xa1, 0x72, 0x27, 0x08, 0x60, 0x28, 0xa9, 0x20, 0x66, 0xb3, 0xab, 0x35, 0xa4, 0xe9]
for i in range(0,len(bit_arr)):
idx = bit_arr[i]
if (idx == 1):
v63 = int(i / 8)
original_flag[v63] ^= 1 << (7 - i % 8);
print(original_flag)
string = ''.join(chr(num) for num in original_flag)
print(string)
IPython.embed() puts("\nCorrect! Attempting to decrypt the flag...", &v65, v23, v24);
v68 = v61 - 1LL;
v41 = 16 * ((v61 + 15LL) / 0x10uLL);
while ( &v54 != (__int64 *)((char *)&v54 - (v41 & 0xFFFFFFFFFFFFF000LL)) )
;
v42 = alloca(v41 & 0xFFF);
if ( (v41 & 0xFFF) != 0 )
*(__int64 *)((char *)&v54 + (v41 & 0xFFF) - 8) = *(__int64 *)((char *)&v54 + (v41 & 0xFFF) - 8);
v69 = &v54;
v43 = v74;
j_memcpy(&v54, v74, v61);
v59 = 0;
for ( i = 0; i < (int)v62; ++i )
What is middle part doing?for ( i = 0; i < (int)val_368; ++i )
{
v47 = calculate((unsigned int)&v54, (_DWORD)v43, i, v44, v45, v46, v73[3 * i], v73[3 * i + 1], v73[3 * i + 2]);
if ( (unsigned __int8)gauntlet(v47) )
{
v63 = i / 8;
v64 = i % 8;
LODWORD(v43) = 1 << (7 - i % 8);
v44 = (unsigned int)v43 ^ *((unsigned __int8 *)flag_shit + i / 8);
*((_BYTE *)flag_shit + v63) ^= 1 << (7 - i % 8);
++v59;
}
} puts("\nCorrect! Attempting to decrypt the flag...", &v65, v23, v24);
v68 = v61 - 1LL;
v41 = 16 * ((v61 + 15LL) / 0x10uLL);
while ( &v54 != (__int64 *)((char *)&v54 - (v41 & 0xFFFFFFFFFFFFF000LL)) )
;
v42 = alloca(v41 & 0xFFF);
if ( (v41 & 0xFFF) != 0 )
*(__int64 *)((char *)&v54 + (v41 & 0xFFF) - 8) = *(__int64 *)((char *)&v54 + (v41 & 0xFFF) - 8);
v69 = &v54;
v43 = v74;
j_memcpy(&v54, v74, v61);
v59 = 0;
for ( i = 0; i < (int)v62; ++i )
What is middle part doing? v71 = 0x10EEB90001E1C34BLL; // these are the encoded bytes
v72 = 0xCB382178A4F04BEELL;
v73 = 0xE84683CE6B212AEALL;
v74 = 0xA0F5CF092C8CA741LL;
v75 = 0x20A92860082772A1LL;
v76 = 900445030;
v77 = 0xE9A4;
These make up the encoded bytes that goes through the for loop (edited) v71 = 0x10EEB90001E1C34BLL; // these are the encoded bytes
v72 = 0xCB382178A4F04BEELL;
v73 = 0xE84683CE6B212AEALL;
v74 = 0xA0F5CF092C8CA741LL;
v75 = 0x20A92860082772A1LL;
v76 = 900445030;
v77 = 0xE9A4;
These make up the encoded bytes that goes through the for loop (edited)uiuctf{This is a fake flag. You are too fast!} -> idk what too fast means v71 = 0x10EEB90001E1C34BLL; // these are the encoded bytes
v72 = 0xCB382178A4F04BEELL;
v73 = 0xE84683CE6B212AEALL;
v74 = 0xA0F5CF092C8CA741LL;
v75 = 0x20A92860082772A1LL;
v76 = 900445030;
v77 = 0xE9A4;
These make up the encoded bytes that goes through the for loop (edited) const_45 = const_46 - 1LL;
const_num = 16 * ((const_46 + 15LL) / 0x10uLL);>>> bin(ord(" "))[2:].zfill(8)
'00100000'
>>> bin(ord("_"))[2:].zfill(8)
'01011111'
btw kinda wondering if the should be replaced by _, looking at this seems all bits except upper bit are shiftedv62 = 368 this prob is usefulfor ( i = 0; i < (int)val_368; ++i )
{
v44 = calculate(
*(_QWORD *)&big_byte_array[0x18 * i - 0x30],// these are arguments on the stack
*(double *)&big_byte_array[0x18 * i - 0x28],
*(double *)&big_byte_array[0x18 * i - 0x20]);
if ( gauntlet(v44) )
{
v60 = i / 8;
v61 = i % 8;
v41 = (1 << (7 - i % 8)) ^ *((unsigned __int8 *)flag_shit + i / 8);
*((_BYTE *)flag_shit + v60) ^= 1 << (7 - i % 8);
++v56;
}
}
4. The number of times that gauntlet returns true are constant every iteration
5. The original flag_shit variable is across every iteration (edited)import IPython
bit_arr = [0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0]
original_flag = [0x4b, 0xc3, 0xe1, 0x01, 0x00, 0xb9, 0xee, 0x10, 0xee, 0x4b, 0xf0, 0xa4, 0x78, 0x21, 0x38, 0xcb, 0xea, 0x2a, 0x21, 0x6b, 0xce, 0x83, 0x46, 0xe8, 0x41, 0xa7, 0x8c, 0x2c, 0x09, 0xcf, 0xf5, 0xa0, 0xa1, 0x72, 0x27, 0x08, 0x60, 0x28, 0xa9, 0x20, 0x66, 0xb3, 0xab, 0x35, 0xa4, 0xe9]
for i in range(0,len(bit_arr)):
idx = bit_arr[i]
if (idx == 1):
v63 = int(i / 8)
original_flag[v63] ^= 1 << (7 - i % 8);
print(original_flag)
string = ''.join(chr(num) for num in original_flag)
print(string)
IPython.embed() import IPython
bit_arr = [0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0]
original_flag = [0x4b, 0xc3, 0xe1, 0x01, 0x00, 0xb9, 0xee, 0x10, 0xee, 0x4b, 0xf0, 0xa4, 0x78, 0x21, 0x38, 0xcb, 0xea, 0x2a, 0x21, 0x6b, 0xce, 0x83, 0x46, 0xe8, 0x41, 0xa7, 0x8c, 0x2c, 0x09, 0xcf, 0xf5, 0xa0, 0xa1, 0x72, 0x27, 0x08, 0x60, 0x28, 0xa9, 0x20, 0x66, 0xb3, 0xab, 0x35, 0xa4, 0xe9]
for i in range(0,len(bit_arr)):
idx = bit_arr[i]
if (idx == 1):
v63 = int(i / 8)
original_flag[v63] ^= 1 << (7 - i % 8);
print(original_flag)
string = ''.join(chr(num) for num in original_flag)
print(string)
IPython.embed() for ( i = 0; i < (int)val_368; ++i )
{
v44 = calculate(
*(_QWORD *)&big_byte_array[0x18 * i - 0x30],// these are arguments on the stack
*(double *)&big_byte_array[0x18 * i - 0x28],
*(double *)&big_byte_array[0x18 * i - 0x20]);
if ( gauntlet(v44) )
{
v60 = i / 8;
v61 = i % 8;
v41 = (1 << (7 - i % 8)) ^ *((unsigned __int8 *)flag_shit + i / 8);
*((_BYTE *)flag_shit + v60) ^= 1 << (7 - i % 8);
++v56;
}
}
4. The number of times that gauntlet returns true are constant every iteration
5. The original flag_shit variable is across every iteration (edited)decompilation is ugly, originally it looks like this:
for ( i = 0; i < (int)v62; ++i )
{
v47 = calculate((unsigned int)&v54, (_DWORD)v43, i, v44, v45, v46, v73[3 * i], v73[3 * i + 1], v73[3 * i + 2]);
if ( (unsigned __int8)gauntlet(v47) )
{
v63 = i / 8;
v64 = i % 8;
LODWORD(v43) = 1 << (7 - i % 8);
v44 = (unsigned int)v43 ^ *((unsigned __int8 *)v69 + i / 8);
*((_BYTE *)v69 + v63) ^= 1 << (7 - i % 8);
++v59;
}
}v44 is used in calculatedouble __fastcall calculate(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, double a7, double a8, double a9, double a10, double a11, double a12, double a13, double a14, unsigned int a15, double a16, double a17)
{
double v10; // [rsp+8h] [rbp-8h]
v10 = 0.0;
if ( a15 > 0x2F )
{
if ( a15 == 94 )
v10 = powf64(a16, a17);
}
else if ( a15 >= 0x25 && a15 - 37 <= 0xA )
{
__asm { jmp rax }
}
return v10;
}
But in calculate it just uses a15, a16, and a17 (edited)for ( i = 0; i < (int)val_368; ++i )
{
v44 = calculate(
*(_QWORD *)&big_byte_array[0x18 * i - 0x30],// these are arguments on the stack
*(double *)&big_byte_array[0x18 * i - 0x28],
*(double *)&big_byte_array[0x18 * i - 0x20]);
if ( gauntlet(v44) )
{
v60 = i / 8;
v61 = i % 8;
v41 = (1 << (7 - i % 8)) ^ *((unsigned __int8 *)flag_shit + i / 8);
*((_BYTE *)flag_shit + v60) ^= 1 << (7 - i % 8);
++v56;
}
}
4. The number of times that gauntlet returns true are constant every iteration
5. The original flag_shit variable is across every iteration (edited)uiuctf{Ahis is a fake flag. You are too fast!}
uiuctf{Bhis is a fake flag. You are too fast!}
uiuctf{Chis is a fake flag. You are too fast!}
uiuctf{Dhis is a fake flag. You are too fast!}
uiuctf{Ehis is a fake flag. You are too fast!}
uiuctf{Fhis is a fake flag. You are too fast!}
uiuctf{Ghis is a fake flag. You are too fast!}
uiuctf{Hhis is a fake flag. You are too fast!}
uiuctf{Ihis is a fake flag. You are too fast!}
uiuctf{Jhis is a fake flag. You are too fast!}
uiuctf{Khis is a fake flag. You are too fast!}
uiuctf{Lhis is a fake flag. You are too fast!}
uiuctf{Mhis is a fake flag. You are too fast!}
uiuctf{Nhis is a fake flag. You are too fast!}
uiuctf{Ohis is a fake flag. You are too fast!}
uiuctf{phis is a fake flag. You are too fast!}
uiuctf{qhis is a fake flag. You are too fast!}
uiuctf{rhis is a fake flag. You are too fast!}
Eg for the first charuse this makefile to build HexRaysDeob for LinuxC:\Users\User\Desktop\HexRaysDeob-master\HexRaysDeob-master\bin\IDA72_32Windows
Once you have a copy of the plug-in, installing the plug-in is as simple as copying the Python file into the plugins folder. For IDA 6.9, the default installation path can be found at:
https://first-plugin-ida.readthedocs.io/en/latest/installing.htmlfor ( i = 0; i < (int)val_368; ++i )
{
v44 = calculate(
*(_QWORD *)&big_byte_array[0x18 * i - 0x30],// these are arguments on the stack
*(double *)&big_byte_array[0x18 * i - 0x28],
*(double *)&big_byte_array[0x18 * i - 0x20]);00:0000│ rsp 0x7fffffffaf50 ◂— 0x25 /* '%' */
01:0008│ 0x7fffffffaf58 ◂— 0x4073a3c584d895d0
02:0010│ 0x7fffffffaf60 ◂— 0xc0757ccd8b26163a.rodata:00000000004B8240 asc_4B8240 db '%',0 ; DATA XREF: main+A0↑o
.rodata:00000000004B8242 align 8
.rodata:00000000004B8248 db 0D0h
.rodata:00000000004B8249 db 95h
.rodata:00000000004B824A db 0D8h
.rodata:00000000004B824B db 84h
.rodata:00000000004B824C db 0C5h
.rodata:00000000004B824D db 0A3h
.rodata:00000000004B824E db 73h ; s
.rodata:00000000004B824F db 40h ; @
.rodata:00000000004B8250 db 3Ah ; :
.rodata:00000000004B8251 db 16h
.rodata:00000000004B8252 db 26h ; &
.rodata:00000000004B8253 db 8Bh
Oh it came from here.rodata:00000000004B8240 asc_4B8240 db '%',0 ; DATA XREF: main+A0↑o
.rodata:00000000004B8242 align 8
.rodata:00000000004B8248 db 0D0h
.rodata:00000000004B8249 db 95h
.rodata:00000000004B824A db 0D8h
.rodata:00000000004B824B db 84h
.rodata:00000000004B824C db 0C5h
.rodata:00000000004B824D db 0A3h
.rodata:00000000004B824E db 73h ; s
.rodata:00000000004B824F db 40h ; @
.rodata:00000000004B8250 db 3Ah ; :
.rodata:00000000004B8251 db 16h
.rodata:00000000004B8252 db 26h ; &
.rodata:00000000004B8253 db 8Bh
Oh it came from here v3 = (__int64 *)"%";
j_memcpy(v73, "%", sizeof(v73)); ---> memcpy the big array
v74[0] = 0x10EEB90001E1C34BLL;
v74[1] = 0xCB382178A4F04BEELL;
v74[2] = 0xE84683CE6B212AEALL;
v74[3] = 0xA0F5CF092C8CA741LL;
v74[4] = 0x20A92860082772A1LL;
All the way at the start
Copy code
import idaapi
import idautils
import idc
# Plugin skeleton
class alloca_deobfuscator_t(idaapi.plugin_t):
flags = 0
comment = "Deobfuscate alloca() obfuscation"
help = "No help"
wanted_name = "Alloca Deobfuscator"
wanted_hotkey = "Ctrl-Shift-A"
def init(self):
self.hotkey_ctx = ida_kernwin.add_hotkey(self.wanted_hotkey, self.run)
if self.hotkey_ctx is None:
return idaapi.PLUGIN_SKIP
else:
return idaapi.PLUGIN_KEEP
def term(self):
ida_kernwin.del_hotkey(self.hotkey_ctx)
def run(self, arg):
# Get a list of all functions in the binary
for func_ea in idautils.Functions():
f = ida_funcs.get_func(func_ea)
if not f:
continue
func_name = ida_funcs.get_func_name(func_ea)
# Iterate over all instructions in the function
for head in idautils.Heads(f.start_ea, f.end_ea):
if ida_ua.is_call_insn(head):
# Get callee address if it's a direct call
callee = idc.get_operand_value(head, 0)
callee_name = ida_name.get_name(callee)
if callee_name == "alloca":
# Check if alloca argument is a constant
if idc.get_operand_type(head, 1) == idc.o_imm:
alloca_size = idc.get_operand_value(head, 1)
# Modify stack frame size
f.frame_regs.sp = f.frame_regs.sp - alloca_size
ida_funcs.set_func_frame(f)
# Force re-analysis of the function
ida_auto.auto_wait()
ida_auto.plan_and_wait(f.start_ea, f.end_ea)
print(f"Deobfuscated alloca call in {func_name}")
print("Finished deobfuscation.")
def run(self, arg):
self.deobfuscate_alloca()
def PLUGIN_ENTRY():
return alloca_deobfuscator_t()import idaapi
import idautils
import idc
# Plugin skeleton
class alloca_deobfuscator_t(idaapi.plugin_t):
flags = 0
comment = "Deobfuscate alloca() obfuscation"
help = "No help"
wanted_name = "Alloca Deobfuscator"
wanted_hotkey = "Ctrl-Shift-A"
def init(self):
self.hotkey_ctx = ida_kernwin.add_hotkey(self.wanted_hotkey, self.run)
if self.hotkey_ctx is None:
return idaapi.PLUGIN_SKIP
else:
return idaapi.PLUGIN_KEEP
def term(self):
ida_kernwin.del_hotkey(self.hotkey_ctx)
def run(self, arg):
# Get a list of all functions in the binary
for func_ea in idautils.Functions():
f = ida_funcs.get_func(func_ea)
if not f:
continue
func_name = ida_funcs.get_func_name(func_ea)
# Iterate over all instructions in the function
for head in idautils.Heads(f.start_ea, f.end_ea):
if ida_ua.is_call_insn(head):
# Get callee address if it's a direct call
callee = idc.get_operand_value(head, 0)
callee_name = ida_name.get_name(callee)
if callee_name == "alloca":
# Check if alloca argument is a constant
if idc.get_operand_type(head, 1) == idc.o_imm:
alloca_size = idc.get_operand_value(head, 1)
# Modify stack frame size
f.frame_regs.sp = f.frame_regs.sp - alloca_size
ida_funcs.set_func_frame(f)
# Force re-analysis of the function
ida_auto.auto_wait()
ida_auto.plan_and_wait(f.start_ea, f.end_ea)
print(f"Deobfuscated alloca call in {func_name}")
print("Finished deobfuscation.")
def run(self, arg):
self.deobfuscate_alloca()
def PLUGIN_ENTRY():
return alloca_deobfuscator_t()c++
for (auto g : af.m_FixupLocations)
{
// Set the stack point on the *subsequent* EA (thanks, Hex-Rays!)
ea_t eaNext = get_item_end(g.first);
msg("[I] Adding auto stack point at %a: %d\n", eaNext, -g.second);
// ... fix its stack pointer differential
if (!add_auto_stkpnt(f, eaNext, -g.second))
{
msg("[E] Couldn't change stack delta to %d at %a\n", -g.second, g.first);
// YOLO
add_user_stkpnt(eaNext, -g.second);
}
}secret operation thing mean anything?If you enter the correct secret operation, I might decrypt the flag for you! ^-^uiuctf{ is fixedoriginal_flag = [0x4b, 0xc3, 0xe1, 0x01, 0x00, 0xb9, 0xee, 0x10, 0xee, 0x4b, 0xf0, 0xa4, 0x78, 0x21, 0x38, 0xcb, 0xea, 0x2a, 0x21, 0x6b, 0xce, 0x83, 0x46, 0xe8, 0x41, 0xa7, 0x8c, 0x2c, 0x09, 0xcf, 0xf5, 0xa0, 0xa1, 0x72, 0x27, 0x08, 0x60, 0x28, 0xa9, 0x20, 0x66, 0xb3, 0xab, 0x35, 0xa4, 0xe9]original_flag = [0x4b, 0xc3, 0xe1, 0x01, 0x00, 0xb9, 0xee, 0x10, 0xee, 0x4b, 0xf0, 0xa4, 0x78, 0x21, 0x38, 0xcb, 0xea, 0x2a, 0x21, 0x6b, 0xce, 0x83, 0x46, 0xe8, 0x41, 0xa7, 0x8c, 0x2c, 0x09, 0xcf, 0xf5, 0xa0, 0xa1, 0x72, 0x27, 0x08, 0x60, 0x28, 0xa9, 0x20, 0x66, 0xb3, 0xab, 0x35, 0xa4, 0xe9] 00111110101010101001010001100010011101001101111110010101010001001000011000100010100000111000010000010001010100100001100010101010110010100100110001000000000000001010101110100011001000001000010000100000110000001010001000001100010100001010000010000000100000001100000000000000010000100010100000010100010001111100011000000000000000001101001011011000010000011000010110010100uiuctf{This_is_a_fake_flag._You_are_too_fast!} so maybe somehting like this ? (edited)uiuctf{This_is_a_real_flag._You_are_too_good!}
T: p@XTRQ 8421
h: >&*,/^FJLOvz|bdghkm
i: {coijS_YZGABMNH
s: 8421@XTRQhdba|zyvus
: d4, &%
i: (0<:9HP\ZY`ljitrq~}{
s: QIEC@yuspmkhgdb=;8742/,*&
: Xhp|zy ,*)421>=;
a: syzgabmnhWQR]^XEF@L
Able to make any guesses? lolThis The operation values are the same, but you may need to check some of the functions used to compute the operation... they might have issuesdouble __fastcall calculate(
__int64 a1,
__int64 a2,
__int64 a3,
__int64 a4,
__int64 a5,
__int64 a6,
double a7,
double a8,
double a9,
double a10,
double a11,
double a12,
double a13,
double a14,
unsigned int a15,
double a16,
double a17)
{
double v10; // [rsp+8h] [rbp-8h]
v10 = 0.0;
if ( a15 > '/' )
{
if ( a15 == '^' )
return powf64(a16, a17);
}
else if ( a15 >= '%' )
{
switch ( a15 )
{
case '%':
v10 = fmodf64(a16, a17);
break;
case '*':
v10 = a17 * a16;
break;
case '+':
v10 = a17 + a16;
break;
case '-':
v10 = a16 - a17;
break;
case '/':
v10 = a16 / a17;
break;
default:
return v10;
}
}
return v10;
}Functions resulting in wrong values, correct#!/usr/bin/python3
import struct
from pwn import *
from decimal import Decimal
with open("./calc", "rb") as f:
biny = f.read()
f.close()
enc = [0x4B, 0xC3, 0xE1, 0x01, 0x00, 0xB9, 0xEE, 0x10, 0xEE, 0x4B,
0xF0, 0xA4, 0x78, 0x21, 0x38, 0xCB, 0xEA, 0x2A, 0x21, 0x6B,
0xCE, 0x83, 0x46, 0xE8, 0x41, 0xA7, 0x8C, 0x2C, 0x09, 0xCF,
0xF5, 0xA0, 0xA1, 0x72, 0x27, 0x08, 0x60, 0x28, 0xA9, 0x20,
0x66, 0xB3, 0xAB, 0x35, 0xA4, 0xE9]
c = 0xb8240
ops = biny[c:c + 0x2280]
v16 = 0
j = 0
for i in range(0, len(ops), 24):
eq = ops[i:i+24]
o = chr(u64(eq[:8]))
x = str(Decimal.from_float(struct.unpack('<d', eq[8:16])[0]))
y = str(Decimal.from_float(struct.unpack('<d', eq[16:24])[0]))
if (o == "%"):
e = x + o + y
elif (o == "*"):
e = y + o + x
elif (o == "+"):
e = y + o + x
elif (o == "-"):
e = x + o + y
elif (o == "/"):
e = x + o + y
elif (o == "^"):
e = f"pow({x}, {y})"
res = eval(e)
if (("j" in str(res)) or (res < 0)):
v20 = j / 8;
v21 = j % 8;
enc[int(j / 8)] ^= 1 << (7 - j % 8);
v16 += 1
j += 1
print(v16)
print(b"".join([bytearray([i]) for i in enc]))Expression: 314.23572239497753 % -343.80018153073945 = Result: -29.564459135761922
Yeah the first char is negativefinal_res = []
function isNegative(num) {
if (Math.sign(num) === -1) {
return true;
}
return false;
}
for (let i = 0; i < arr.length; i++) {
result = eval(arr[i]);
console.log(result)
if (isNegative(result)){
final_res.push(1);
}
else if (Object.is(result, -0)){
final_res.push(1);
}
else{
final_res.push(0);
}
}final_res = []
function isNegative(num) {
if (Math.sign(num) === -1) {
return true;
}
return false;
}
for (let i = 0; i < arr.length; i++) {
result = eval(arr[i]);
console.log(result)
if (isNegative(result)){
final_res.push(1);
}
else if (Object.is(result, -0)){
final_res.push(1);
}
else{
final_res.push(0);
}
} Object.is